﻿using M3u8Puller.Config;
using M3u8Puller.Entity;
using M3u8Puller.Kit;
using Microsoft.VisualBasic;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using static System.Windows.Forms.VisualStyles.VisualStyleElement;

namespace M3u8Puller
{
    public partial class FrmMain : Form
    {
        List<M3u8TaskEntity> tasks = new List<M3u8TaskEntity>();
        static string downListFile = AppDomain.CurrentDomain.BaseDirectory + "\\DownList.Json";

        public static Icon icon = Icon.ExtractAssociatedIcon(Assembly.GetExecutingAssembly().Location);
        public FrmMain()
        {
            InitializeComponent();
            this.notifyIcon1.Icon = icon;
            this.timer1.Interval = 1000 * 60;
        }

        private void 添加任务ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            FrmTaskAdd frm = new FrmTaskAdd(this);
            frm.Left = this.Left + (this.Width - frm.Width) / 2;
            frm.Top = this.Top + (this.Height - frm.Height) / 2;
            frm.ShowDialog();
        }

        private void InitDownListConfig()
        {
            try
            {
                if (!File.Exists(downListFile))
                {
                    var st = File.CreateText(downListFile);
                    st.Write(JsonConvert.SerializeObject(tasks));
                    st.Dispose();
                }
                var json = File.ReadAllText(downListFile);
                tasks = JsonConvert.DeserializeObject<List<M3u8TaskEntity>>(json);
                if (tasks.Any())
                    SeqKit.current = tasks.Max(x => x.Id);
                ;
                tasks.ForEach(task =>
                {
                    if (task.Status != -1)
                    {
                        AddTask(task, false);
                        //task.M3u8TaskStart();
                    }
                });
            }
            catch (Exception ex)
            {
                MessageBox.Show("error:" + ex.Message);
                tasks = new List<M3u8TaskEntity>();
            }
        }

        public void SaveDownListConfig()
        {
            try
            {
                if (!File.Exists(downListFile))
                {
                    var st = File.CreateText(downListFile);
                    st.Write(JsonConvert.SerializeObject(tasks));
                    st.Dispose();
                }
                else
                {
                    File.WriteAllText(downListFile, JsonConvert.SerializeObject(tasks));
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show("error:" + ex.Message);
                tasks = new List<M3u8TaskEntity>();
            }
        }

        private void FrmMain_Load(object sender, EventArgs e)
        {
            InitDownListConfig();

            this.Icon = icon;

            Task.Factory.StartNew(() =>
            {
                while (true)
                {
                    Thread.Sleep(100);
                    lock (this)
                    {
                        int thread = 0;
                        foreach (M3u8TaskEntity task in tasks)
                        {
                            if (task.Status == 1)
                            {
                                thread++;
                            }
                        }

                        for (int i = thread; i < SystemConfig.TaskParallel; i++)
                        {
                            foreach (M3u8TaskEntity task in tasks)
                            {
                                if (task.Status == 0)
                                {
                                    Task.Factory.StartNew(() =>
                                    {
                                        task.Status = 1;
                                        task.Download();
                                    }, TaskCreationOptions.LongRunning);
                                }
                            }

                        }
                        foreach (M3u8TaskEntity task in tasks)
                        {
                            if (task.Status != 1 && task.Status != 5)
                            {
                                continue;
                            }
                            this.BeginInvoke(new MethodInvoker(() =>
                            {
                                foreach (ListViewItem item in lvClients.Items)
                                {
                                    if (Convert.ToString(item.SubItems[0].Text).Equals(Convert.ToString(task.Id)))
                                    {
                                        double speed = task.CompleteNum * 100D / task.PartNum;
                                        if (speed > 100)
                                        {
                                            speed = 100;
                                        }
                                        item.SubItems[3].Text = String.Format("{0:F}", speed) + "%";
                                    }
                                }
                            }));
                        }
                    }
                }
            }, TaskCreationOptions.LongRunning);
        }

        public void AddTask(M3u8TaskEntity task, bool isSave = true)
        {
            ListViewItem item = new ListViewItem(Convert.ToString(task.Id));
            item.Name = item.Text;
            item.SubItems.Add(task.Url);
            item.SubItems.Add(task.Name);
            item.SubItems.Add(task.StatusName);
            lvClients.Items.Add(item);            

            if (isSave)
            {
                tasks.Add(task);
                SaveDownListConfig();
            }

            Task.Factory.StartNew(() =>
            {
                if (task.Status == 3)
                {
                    task.M3u8TaskStart();

                    if (task.Status == 4)
                    {
                        this.Invoke(new Action(() =>
                        {
                            item.SubItems[3].Text = task.StatusName;
                        }));
                    }
                }
            }, TaskCreationOptions.LongRunning);
        }

        private void 开始任务ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            lock (this)
            {
                try
                {
                    string id = lvClients.SelectedItems[0].SubItems[0].Text;
                    foreach (M3u8TaskEntity task in tasks)
                    {
                        if (Convert.ToString(task.Id).Equals(id))
                        {
                            if (task.Status == 2)
                            {
                                lvClients.SelectedItems[0].SubItems[3].Text = "等待下载";
                                task.Status = 0;
                            }
                            else if (task.Status == 3 || task.Status == 4)
                            {
                                Task.Factory.StartNew(() =>
                                {
                                    task.M3u8TaskStart();
                                }, TaskCreationOptions.LongRunning);
                            }
                        }
                    }
                }
                catch { }
            }
        }

        private void 删除任务ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            lock (this)
            {
                try
                {
                    string id = lvClients.SelectedItems[0].SubItems[0].Text;
                    foreach (M3u8TaskEntity task in tasks)
                    {
                        if (Convert.ToString(task.Id).Equals(id))
                        {
                            task.Status = 2;
                            Task.Run(() =>
                            {
                                Thread.Sleep(3000);
                                task.Status = -1;
                                this.Invoke(new Action(() =>
                                {
                                    lvClients.Items.Remove(lvClients.SelectedItems[0]);
                                }));
                                tasks.RemoveAll(x => x.Status == -1);
                                if (File.Exists(task.Name + ".cache"))
                                    File.Delete(task.Name + ".cache");
                                else if (File.Exists(task.Name))
                                    File.Delete(task.Name);
                                SaveDownListConfig();
                            });
                        }
                    }
                }
                catch { }
            }
        }

        private void 暂停任务ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            lock (this)
            {
                try
                {
                    string id = lvClients.SelectedItems[0].SubItems[0].Text;
                    foreach (M3u8TaskEntity task in tasks)
                    {
                        if (Convert.ToString(task.Id).Equals(id))
                        {
                            lvClients.SelectedItems[0].SubItems[3].Text = "暂停下载";
                            task.Status = 2;
                            SaveDownListConfig();
                        }
                    }
                }
                catch { }
            }
        }

        private void 打开目录ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            lock (this)
            {
                try
                {
                    string path = lvClients.SelectedItems[0].SubItems[2].Text;
                    FileInfo file = new FileInfo(path);

                    System.Diagnostics.Process.Start("explorer.exe", file.Directory.FullName);
                }
                catch { }
            }
        }

        private void 退出程序ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            DialogResult r = MessageBox.Show("真的退出吗?", "提醒", MessageBoxButtons.YesNo);
            if (r == DialogResult.Yes)
            {
                SaveDownListConfig();
                Process.GetCurrentProcess().Kill();
            }
        }

        private void lvClients_SizeChanged(object sender, EventArgs e)
        {
            float colPercentage0 = 0.7F / 10F;
            lvClients.Columns[0].Width = (int)(colPercentage0 * lvClients.ClientRectangle.Width);

            float colPercentage1 = 4 / 10F;
            lvClients.Columns[1].Width = (int)(colPercentage1 * lvClients.ClientRectangle.Width);

            float colPercentage2 = 4 / 10F;
            lvClients.Columns[2].Width = (int)(colPercentage2 * lvClients.ClientRectangle.Width);

            float colPercentage3 = 1.3F / 10F;
            lvClients.Columns[3].Width = (int)(colPercentage3 * lvClients.ClientRectangle.Width);
        }

        private void FrmMain_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (e.CloseReason == CloseReason.UserClosing)
            {
                this.Hide();
                e.Cancel = true;
            }
        }

        private void notifyIcon1_MouseDoubleClick(object sender, MouseEventArgs e)
        {
            if (this.Visible == false) this.Show();
            if (this.WindowState == FormWindowState.Minimized)
                this.WindowState = FormWindowState.Normal;
        }

        private void outsystem_ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            SaveDownListConfig();
            this.Dispose();
        }

        private void 转换ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            string aesKey = Interaction.InputBox("请输入解密key", "标题", "f151232cc9bdc8db", -1, -1);
            if (aesKey == string.Empty)
            {
                MessageBox.Show("解密key不能为空");
                return;
            }
            string sourceFile = Interaction.InputBox("请输入解密文件路径", "标题", "", -1, -1);
            if (sourceFile == string.Empty)
            {
                MessageBox.Show("解密文件不能为空");
                return;
            }
            string targetFile = Interaction.InputBox("请输入输出文件路径", "标题", "", -1, -1);
            if (targetFile == string.Empty)
            {
                MessageBox.Show("输出文件不能为空");
                return;
            }
            var aes = new AESEncoder(aesKey);
            var bo = aes.DecryptFile(sourceFile, targetFile);

            if (bo)
                MessageBox.Show("解密文件成功");
        }

        private void 保存任务ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            SaveDownListConfig();
        }

        private void 设置ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            string str = Interaction.InputBox("请输入保存目录", "提示", AppConfig.GetConfig().DefaultDir, -1, -1);
            if (str == string.Empty)
            {
                MessageBox.Show("保存目录不能为空");
                return;
            }
            var appConfig = AppConfig.GetConfig();
            appConfig.DefaultDir = str;
            AppConfig.SaveConfig(appConfig);
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            SaveDownListConfig();
        }

        private void 转换视频ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            var dialog = new FolderBrowserDialog();
            dialog.Description = "选择m3u8文件夹";
            dialog.SelectedPath = AppConfig.GetConfig().DefaultDir;
            var dialogResult = dialog.ShowDialog();
            if (dialogResult != DialogResult.OK)
                return;
            var folderPath = dialog.SelectedPath;

            var saveFileDialog = new SaveFileDialog();
            saveFileDialog.Title = "保存文件路径";
            saveFileDialog.Filter = "视频文件|*.mp4|所有文件|*.*";
            saveFileDialog.InitialDirectory = AppConfig.GetConfig().DefaultDir;
            if (saveFileDialog.ShowDialog() != DialogResult.OK)
                return;
            var saveFileName = saveFileDialog.FileName;

            var task = new M3u8TaskEntity();
            task.Id = SeqKit.Next();
            task.Name = saveFileName;
            task.Url = folderPath;
            task.Status = 6;
            AddTask(task);

            var t = Task.Factory.StartNew(() =>
            {
                task.ReadTsFile();
                task.Status = 7;
                this.Invoke(new Action(() =>
                {
                    UpdateStatus(task);
                }));

                task.MergeToFile();
                task.Status = 5;
                task.CompleteNum = 1;
                task.PartNum = 1;
                this.Invoke(new Action(() =>
                {
                    UpdateStatus(task);
                }));

            }, TaskCreationOptions.LongRunning);
        }

        private void UpdateStatus(M3u8TaskEntity task)
        {
            var item = lvClients.Items[task.Id.ToString()];
            item.SubItems[3].Text = task.StatusName;
        }
    }
}
